﻿using CodeGenerator.CSharp.Extensions;

namespace CodeGenerator.CSharp
{
    public class Property : CodeUnit
    {

        #region Constructors

		public Property(string name, ModifierCollection modifiers, string dataType) : this(name, modifiers, dataType, string.Empty) { }
        public Property(string name, ModifierCollection modifiers, string dataType, string fieldName) : base(name, modifiers)
        { 
            this.DataType = dataType;
			if (fieldName.Length > 0) this.Field = new Field(fieldName, CodeGenerator.CSharp.Modifiers.Private, dataType);
			this.IsReadOnly = false;
			this.IsWriteOnly = false;
            this.GetModifiers = new ModifierCollection();
            this.SetModifiers = new ModifierCollection();
            this.IsAutoProperty = false;
        }

        #endregion

        #region Field

        /// <summary>
        /// Gets or sets the field that backs this property.
        /// </summary>
        public Field Field { get; set; }

		public Field AddField(string name)
		{
			this.Field = new Field(name, CodeGenerator.CSharp.Modifiers.Private, this.DataType);
			return this.Field;
		}

		public Field AddField(string name, string defaultValue)
		{
			this.Field = new Field(name, CodeGenerator.CSharp.Modifiers.Private, this.DataType);
			this.Field.DefaultValue = defaultValue;
			return this.Field;
		}

		public Field AddField(string name, bool instantiate)
		{
			this.Field = new Field(name, CodeGenerator.CSharp.Modifiers.Private, this.DataType);
			this.Field.Instantiate = instantiate;
			return this.Field;
		}

		public new Field AddField(string name, CodeGenerator.CSharp.ModifierCollection modifiers, string dataType)
		{
			this.Field = new Field(name, modifiers, dataType);
			return this.Field;
		}


        #endregion

        #region Get

        /// <summary>
        /// Identifies the modifiers of the Get portion of this property.
        /// </summary>
        public ModifierCollection GetModifiers { get; set; }
        //public ModifierCollection GetModifiers { get { return this._GetModifiers; } }
        //private ModifierCollection _GetModifiers = new ModifierCollection();

		/// <summary>
		/// Identifies the body of the Get portion of this property.
		/// </summary>
		public Body GetBody
		{
			get
			{
				if (this._GetBody == null) this._GetBody = new Body(this);
				return this._GetBody;
			}
		}
		private Body _GetBody;

        #endregion

        #region Set

        /// <summary>
        /// Identifies the modifiers of the Set portion of this property.
        /// </summary>
        //public ModifierCollection SetModifiers { get { return this._SetModifiers; } }
        //private ModifierCollection _SetModifiers = new ModifierCollection();
        public ModifierCollection SetModifiers { get; set; }

        /// <summary>
		/// Identifies the body of the SetCS portion of this property.
		/// </summary>
		public Body SetBody
		{
			get
			{
				if (this._SetBody == null) this._SetBody = new Body(this);
				return this._SetBody;
			}
		}
		private Body _SetBody;

        #endregion

		#region Read/Write Only

		/// <summary>
		/// Identifies if this property is read only.
		/// </summary>
		public bool IsReadOnly { get; set; }

		/// <summary>
		/// Identifies if this property is write only.
		/// </summary>
		public bool IsWriteOnly { get; set; }

		#endregion

        #region IsAutoProperty

        public bool IsAutoProperty { get; set; }

        #endregion

        #region ToString

        public override string ToString()
        {
            CodeBuilder Code = new CodeBuilder();

            this.AppendDocumentation(Code);
            this.AppendAttributes(Code);

			if (this.Modifiers.IsAbstract)
			{
				string Read_Write_Only = string.Empty;
				if (this.IsReadOnly) 
                    Read_Write_Only = "{ get; }"; 
                else if (this.IsWriteOnly) 
                    Read_Write_Only = "{ set; }";
				Code.Add("{0}{1} {2} {3} {4}", this.Padding, this.Modifiers, this.DataType, this.Name, Read_Write_Only);
			}
            else if (this.IsAutoProperty)
            {
                //string Body = string.Format("{ {0} get; {1} set; }", this.GetModifiers.ToString(), this.SetModifiers.ToString());
                string Body = "{ " + this.GetModifiers.ToString() + " get; " + this.SetModifiers.ToString() + " set; }";
                if (this.IsReadOnly)
                    Body = string.Format("{ {0} get; }", this.GetModifiers.ToString());
                else if (this.IsWriteOnly)
                    Body = string.Format("{ {0} set; }", this.SetModifiers.ToString());
                
                Code.Add("{0}{1} {2} {3} {4}", this.Padding, this.Modifiers, this.DataType, this.Name, Body);
            }
			else
			{
				Code.Add("{0}{1} {2} {3}", this.Padding, this.Modifiers, this.DataType, this.Name);
				if (this._GetBody.IsSomething() || this._SetBody.IsSomething())
				{
					Code.Add(this.Padding + "{");
					if (this._GetBody.IsSomething())
					{
                        string padding = this.Padding;
                        if (this.GetModifiers.Count > 0) padding += "    " + this.GetModifiers.ToString() + " ";
                        Code.Add(this.Padding + "    " + this.SetModifiers.ToString() + "get");
						Code.Add(this.Padding + "    {");
						Code.Add(this._GetBody.ToString());
						Code.Add(this.Padding + "    }");
					}

					if (this._SetBody.IsSomething())
					{
                        Code.Add(this.Padding + "    " + this.SetModifiers.ToString() + "set");
						Code.Add(this.Padding + "    {");
                        Code.Add(this._SetBody.ToString());
						Code.Add(this.Padding + "    }");
					}
					Code.Add(this.Padding + "}");
				}

				if (this.Field.IsSomething())
				{
					this.Field.IndentationLevel = this.IndentationLevel;
					Code.Add(this.Field.ToString());
				}
			}

            return Code.ToString();
        }


        #endregion

    }
}
